home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / xlib / tline.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  15KB  |  666 lines

  1. /*
  2.  * (c) Copyright 1994, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software for
  6.  * any purpose and without fee is hereby granted, provided that the above
  7.  * copyright notice appear in all copies and that both the copyright notice
  8.  * and this permission notice appear in supporting documentation, and that
  9.  * the name of Silicon Graphics, Inc. not be used in advertising
  10.  * or publicity pertaining to distribution of the software without specific,
  11.  * written prior permission.
  12.  *
  13.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  14.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  15.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  16.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  17.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  18.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  19.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  20.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  21.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  22.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  23.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  24.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  25.  *
  26.  * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND
  27.  * Use, duplication, or disclosure by the Government is subject to
  28.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  29.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  30.  * clause at DFARS 252.227-7013 and/or in similar or successor
  31.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  32.  * Unpublished-- rights reserved under the copyright laws of the
  33.  * United States.  Contractor/manufacturer is Silicon Graphics,
  34.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  35.  *
  36.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  37.  */
  38. #include <GL/glx.h>
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <unistd.h>
  42. #include <stdlib.h>
  43. #include <X11/keysym.h>
  44.  
  45. static int RGB_SB_attributes[] = {
  46.     GLX_RGBA,
  47.     GLX_RED_SIZE, 1,
  48.     GLX_GREEN_SIZE, 1,
  49.     GLX_BLUE_SIZE, 1,
  50.     GLX_DEPTH_SIZE, 1,
  51.     GLX_STENCIL_SIZE, 1,
  52.     None,
  53. };
  54.  
  55. static int RGB_DB_attributes[] = {
  56.     GLX_RGBA,
  57.     GLX_RED_SIZE, 1,
  58.     GLX_GREEN_SIZE, 1,
  59.     GLX_BLUE_SIZE, 1,
  60.     GLX_DOUBLEBUFFER,
  61.     GLX_DEPTH_SIZE, 1,
  62.     GLX_STENCIL_SIZE, 1,
  63.     None,
  64. };
  65.  
  66. static int CI_SB_attributes[] = {
  67.     GLX_DEPTH_SIZE, 1,
  68.     GLX_STENCIL_SIZE, 1,
  69.     None,
  70. };
  71.  
  72. static int CI_DB_attributes[] = {
  73.     GLX_DOUBLEBUFFER,
  74.     GLX_DEPTH_SIZE, 1,
  75.     GLX_STENCIL_SIZE, 1,
  76.     None,
  77. };
  78.  
  79. #define SETCOLOR(x) if (rgb) glColor3fv(rgbMap[x]); else glIndexf(x)
  80.  
  81. enum {
  82.     BLACK = 0,
  83.     RED,
  84.     GREEN,
  85.     YELLOW,
  86.     BLUE,
  87.     MAGENTA,
  88.     CYAN,
  89.     WHITE
  90. };
  91.  
  92. #define COLOR_OFFSET    16
  93.  
  94. static float rgbMap[8][3] = {
  95.     {0, 0, 0},
  96.     {1, 0, 0},
  97.     {0, 1, 0},
  98.     {1, 1, 0},
  99.     {0, 0, 1},
  100.     {1, 0, 1},
  101.     {0, 1, 1},
  102.     {1, 1, 1}
  103. };
  104.  
  105. Display *dpy;
  106. Colormap cmap;
  107. Window window;
  108. int rgb = 1;
  109. int doubleBuf = 1;
  110. int W = 300;
  111. int H = 300;
  112.  
  113. static GLint indexBits;
  114. static long ci = YELLOW;
  115. static GLboolean dither = GL_TRUE;
  116. static GLboolean fragment = GL_FALSE;
  117. static GLboolean smoothModel = GL_TRUE;
  118. static long mode1, mode2;
  119. static int blending;
  120. static float size;
  121. static float pntA[3] = {-165, 0, -0.5};
  122. static float pntB[3] = {-60, 0, -0.5};
  123. static float pntC[3] = {-40, -50, -0.5};
  124. static float pntD[3] = {30, 60, -0.5};
  125. static float pntAAB[3] = {-150, 0, -0.5};
  126. static float pntABA[3] = {-140, 0, -0.5};
  127. static float pntABB[3] = {-120, 0, -0.5};
  128. static float pntBAA[3] = {-100, 0, -0.5};
  129. static float pntBAB[3] = {-80, 0, -0.5};
  130. static float pntBBA[3] = {-70, 0, -0.5};
  131. static float zrot = 0.0;
  132. static float dzrot = 0.0;
  133. static int stenciling = 0;
  134. static int depthtest = 1;
  135. static int alwayspass = 0;
  136. static int depthMask = 0;
  137.  
  138. static void SetUpColorMap(void)
  139. {
  140.     XColor *xc;
  141.     float color;
  142.     long i, j, cells;
  143.  
  144.     if (indexBits < 5) return;
  145.     
  146.     cells = 16;
  147.     xc = (XColor *) malloc(cells * sizeof(XColor));
  148.  
  149.     for (i = 0; i < 16; i++) {
  150.     xc[i].pixel = i + COLOR_OFFSET;
  151.     xc[i].red = i * 4369;
  152.     xc[i].green = i * 4369;
  153.     xc[i].blue = 0;
  154.     xc[i].flags = DoRed | DoGreen | DoBlue;
  155.     }
  156.     XStoreColors(dpy, cmap, xc, cells);
  157.  
  158.     free((void *) xc);
  159. }
  160.  
  161. static void Init(void)
  162. {
  163.     if (!rgb) {
  164.     glGetIntegerv(GL_INDEX_BITS, &indexBits);
  165.         SetUpColorMap();
  166.     }
  167.  
  168.     mode1 = 0;
  169.     mode2 = 0;
  170.     size = 1;
  171.  
  172.     glViewport(10, 10, W-20, H-20);
  173.     glMatrixMode(GL_PROJECTION);
  174.     glLoadIdentity();
  175.     glOrtho(-175, 175, -175, 175, -1, 1);
  176.     glMatrixMode(GL_MODELVIEW);
  177.  
  178. }
  179.  
  180. static void Redraw(void)
  181. {
  182.     long i;
  183.  
  184.     if (dzrot != 0.0) {
  185.     zrot += dzrot;
  186.     }
  187.  
  188.     glClearColor(0.0, 0.0, 0.0, 0.0);
  189.  
  190.     glClear(GL_COLOR_BUFFER_BIT);
  191.  
  192.     glLineWidth(3);
  193.     glDisable(GL_LINE_STIPPLE);
  194.     glDisable(GL_LINE_SMOOTH);
  195.     glDisable(GL_BLEND);
  196.  
  197.     if (depthtest) {
  198.     glClearDepth(1.0);
  199.     glClear(GL_DEPTH_BUFFER_BIT);
  200.     glEnable(GL_DEPTH_TEST);
  201.     if (alwayspass) {
  202.         glDepthFunc(GL_ALWAYS);
  203.     } else {
  204.         glDepthFunc(GL_LESS);
  205.     }
  206.  
  207.     SETCOLOR(MAGENTA);
  208.     glBegin(GL_LINES);
  209.     for (i = -8; i <= 8; i++) {
  210.         glVertex3f(i*20, -175, 0);
  211.         glVertex3f(i*20,  175, 0);
  212.     }
  213.     if (depthMask) {
  214.         glEnd();
  215.         glDepthMask(GL_FALSE);
  216.         glBegin(GL_LINES);
  217.     }
  218.     for (i = -8; i <= 8; i++) {
  219.         glVertex3f(-175, i*20, 0);
  220.         glVertex3f( 175, i*20, 0);
  221.     }
  222.     glEnd();
  223.     if (depthMask) {
  224.         glDepthMask(GL_TRUE);
  225.     }
  226.     }
  227.  
  228.     if (stenciling) {
  229.     SETCOLOR(BLACK);
  230.  
  231.         glClearStencil(0);
  232.         glClear(GL_STENCIL_BUFFER_BIT);
  233.  
  234.     glEnable(GL_STENCIL_TEST);
  235.         glStencilFunc(GL_ALWAYS, 1, 3);
  236.         glStencilOp(GL_KEEP, GL_INVERT, GL_REPLACE);
  237.  
  238.     glBegin(GL_LINES);
  239.     for (i = -10; i <= 10; i++) {
  240.         glVertex3f(i*17, -175, -0.5);
  241.         glVertex3f(i*17,  175, -0.5);
  242.     }
  243.     for (i = -10; i <= 10; i++) {
  244.         glVertex3f(-175, i*17, -0.5);
  245.         glVertex3f( 175, i*17, -0.5);
  246.     }
  247.     glEnd();
  248.  
  249.     glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT);
  250.  
  251.     if (depthtest) {
  252.         SETCOLOR(RED);
  253.         glStencilFunc(GL_EQUAL, 3, 3);
  254.         glDisable(GL_DEPTH_TEST);
  255.         glBegin(GL_QUADS);
  256.         glVertex3f(-175, -175, -0.5);
  257.         glVertex3f(-175,  175, -0.5);
  258.         glVertex3f( 175,  175, -0.5);
  259.         glVertex3f( 175, -175, -0.5);
  260.         glEnd();
  261.         glEnable(GL_DEPTH_TEST);
  262.     }
  263.  
  264.     glStencilOp(GL_KEEP, GL_INVERT, GL_KEEP);
  265.     glStencilFunc(GL_NOTEQUAL, 1, 1);
  266.     }
  267.  
  268.     glLineWidth(size);
  269.     if (mode1) {
  270.     glEnable(GL_LINE_STIPPLE);
  271.     } else {
  272.     glDisable(GL_LINE_STIPPLE);
  273.     }
  274.     glLineStipple(1, 0xF0E0);
  275.     
  276.     if (blending) {
  277.     glEnable(GL_BLEND);
  278.     glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
  279.     }
  280.  
  281.     if (mode2) {
  282.     glEnable(GL_LINE_SMOOTH);
  283.     if (mode2 > 1) {
  284.         glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  285.     } else {
  286.         glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
  287.     }
  288.     } else {
  289.     glDisable(GL_LINE_SMOOTH);
  290.     }
  291.  
  292.     glPushMatrix();
  293.     glRotatef(zrot, 0,0,1);
  294.     for (i = 0; i < 360; i += 5) {
  295.     glRotatef(5.0, 0,0,1);
  296.  
  297.     if (rgb) glColor3fv(rgbMap[YELLOW]); else glIndexi(ci);
  298.     glBegin(GL_LINE_STRIP);
  299.     if (fragment) {
  300.         glVertex3fv(pntA);
  301.         glVertex3fv(pntAAB);
  302.         glVertex3fv(pntABA);
  303.         glVertex3fv(pntABB);
  304.         if (rgb || !mode2) {
  305.         SETCOLOR(CYAN);
  306.         }
  307.         glVertex3fv(pntBAA);
  308.         glVertex3fv(pntBAB);
  309.         glVertex3fv(pntBBA);
  310.         glVertex3fv(pntB);
  311.     } else {
  312.         glVertex3fv(pntA);
  313.         if (rgb || !mode2) {
  314.         SETCOLOR(CYAN);
  315.         }
  316.         glVertex3fv(pntB);
  317.     }
  318.     glEnd();
  319.  
  320.     SETCOLOR(GREEN);
  321.     }
  322.     glPopMatrix();
  323.  
  324.     glFlush();
  325.  
  326.     if (depthtest) {
  327.     glDisable(GL_DEPTH_TEST);
  328.  
  329.     if (stenciling) {
  330.         SETCOLOR(WHITE);
  331.         glStencilFunc(GL_EQUAL, 3, 3);
  332.         glBegin(GL_QUADS);
  333.         glVertex3f(-175, -175, -0.5);
  334.         glVertex3f(-175,  175, -0.5);
  335.         glVertex3f( 175,  175, -0.5);
  336.         glVertex3f( 175, -175, -0.5);
  337.         glEnd();
  338.     }
  339.     }
  340.  
  341.     if (stenciling) {
  342.     glDisable(GL_STENCIL_TEST);
  343.     }
  344.  
  345.     if (doubleBuf) {
  346.     glXSwapBuffers(dpy, window);
  347.     }
  348. }
  349.  
  350. static void Usage(void)
  351. {
  352.     fprintf(stderr, "Usage: program [-c] [-s] [-geometry WxH+X+Y]\n");
  353.     fprintf(stderr, " -c  run in color index mode\n");
  354.     fprintf(stderr, " -s  run in singlebuffer mode\n");
  355.     fprintf(stderr, " -geometry   window size and location\n");
  356.     exit(1);
  357. }
  358.  
  359. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  360. {
  361.     if ((e->type == MapNotify) && (e->xmap.window == (Window) arg)) {
  362.     return GL_TRUE;
  363.     }
  364.     return GL_FALSE;
  365. }
  366.  
  367. int main(int argc, char** argv)
  368. {
  369.     XVisualInfo *vi;
  370.     XSetWindowAttributes swa;
  371.     GLXContext cx;
  372.     XEvent event;
  373.     GLboolean needDisplay;
  374.     XColor black;
  375.     int i;
  376.     XSizeHints sizehints;
  377.     char *geometry = NULL;
  378.  
  379.     rgb = 1;
  380.     for (i = 1; i < argc; i++) {
  381.         if (argv[i][0] == '-') {
  382.         if (strcmp(argv[i], "-geometry") == 0) {
  383.         i++;
  384.         geometry = argv[i];
  385.         } else switch (argv[i][1]) {
  386.               case 'c':
  387.                 rgb = GL_FALSE;
  388.                 break;
  389.           case 's':
  390.         doubleBuf = 0;
  391.         break;
  392.               default:
  393.                 Usage();
  394.             }
  395.         } else {
  396.             Usage();
  397.         }
  398.     }
  399.  
  400.     dpy = XOpenDisplay(0);
  401.     if (!dpy) {
  402.     fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY"));
  403.     return -1;
  404.     }
  405.  
  406.     vi = glXChooseVisual(dpy, DefaultScreen(dpy),
  407.         doubleBuf ? (rgb ? RGB_DB_attributes : CI_DB_attributes) :
  408.         (rgb ? RGB_SB_attributes : CI_SB_attributes));
  409.     if (!vi) {
  410.     fprintf(stderr, "No singlebuffered rgba visual on \"%s\"\n",
  411.         getenv("DISPLAY"));
  412.     return -1;
  413.     }
  414.  
  415.     sizehints.flags = PPosition | PSize;
  416.     sizehints.width = W;
  417.     sizehints.height = H;
  418.     sizehints.x = 10;
  419.     sizehints.y = 10;
  420.     if(geometry) {
  421.     int flags, x, y, width, height;
  422.  
  423.     flags = XParseGeometry(geometry, &x, &y,
  424.                    (unsigned int *)&width,
  425.                    (unsigned int *)&height);
  426.         if(WidthValue & flags) {
  427.         sizehints.flags |= USSize;
  428.         sizehints.width = width;
  429.         W = width;
  430.     }
  431.     if(HeightValue & flags) {
  432.         sizehints.flags |= USSize;
  433.         sizehints.height = height;
  434.         H = height;
  435.     }
  436.     if(XValue & flags) {
  437.         if(XNegative & flags)
  438.         x = DisplayWidth(dpy, DefaultScreen(dpy)) + x 
  439.             - sizehints.width;
  440.                 sizehints.flags |= USPosition;
  441.         sizehints.x = x;
  442.     }
  443.     if(YValue & flags) {
  444.         if(YNegative & flags)
  445.         y = DisplayHeight(dpy, DefaultScreen(dpy)) + y 
  446.             - sizehints.height;
  447.                 sizehints.flags |= USPosition;
  448.         sizehints.y = y;
  449.     }
  450.     }
  451.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  452.                rgb ? AllocNone : AllocAll);
  453.  
  454.     if (!rgb) {
  455.     XColor buf;
  456.     int i;
  457.  
  458.     buf.flags = DoRed | DoGreen | DoBlue;
  459.  
  460.     /* Init color map */
  461.     for (i=0; i<16; i++) {
  462.         buf.pixel = i;
  463.         buf.blue = (i & 4) ? 65535 : 0;
  464.         buf.green = (i & 2) ? 65535 : 0;
  465.         buf.red = (i & 1) ? 65535 : 0;
  466.         if (i > 8) {
  467.         buf.red /= 2;
  468.         buf.green /= 2;
  469.         buf.blue /= 2;
  470.         }
  471.         XStoreColor(dpy, cmap, &buf);
  472.     }
  473.     }
  474.  
  475.     swa.border_pixel = 0;
  476.     swa.background_pixmap = None;
  477.     swa.colormap = cmap;
  478.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
  479.     | KeyReleaseMask;
  480.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 
  481.                sizehints.x, sizehints.y,
  482.                sizehints.width, sizehints.height,
  483.                0, vi->depth, InputOutput, vi->visual,
  484.                CWBackPixmap|CWBorderPixel|CWColormap|CWEventMask,
  485.                &swa);
  486.     XSetStandardProperties(dpy, window, "tline", "tline", None,
  487.                            argv, argc, &sizehints);
  488.     XSetWMColormapWindows(dpy, window, &window, 1);
  489.     XMapWindow(dpy, window);
  490.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  491.  
  492.     cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
  493.     if (!glXMakeCurrent(dpy, window, cx)) {
  494.     fprintf(stderr, "Can't make window current to context\n");
  495.     return -1;
  496.     }
  497.  
  498.     Init();
  499.  
  500.     needDisplay = GL_TRUE;
  501.     for (;;) {
  502.     if (XPending(dpy) || dzrot == 0.0) do {
  503.         XNextEvent(dpy, &event);
  504.         switch (event.type) {
  505.           case Expose:
  506.         needDisplay = GL_TRUE;
  507.         break;
  508.           case ConfigureNotify:
  509.         W = event.xconfigure.width;
  510.         H = event.xconfigure.height;
  511.         glViewport(10, 10, W-20, H-20);
  512.         glMatrixMode(GL_PROJECTION);
  513.         glLoadIdentity();
  514.         glOrtho(-175, 175, -175, 175, -1, 1);
  515.         glMatrixMode(GL_MODELVIEW);
  516.         needDisplay = GL_TRUE;
  517.         break;
  518.           case KeyPress:
  519.         {
  520.             char buf[100];
  521.             int rv;
  522.             KeySym ks;
  523.             GLboolean setNeed = GL_TRUE;
  524.  
  525.             rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
  526.             switch (ks) {
  527.               case XK_Escape:
  528.             exit(0);
  529.               case XK_Y:
  530.               case XK_y:
  531.             blending = 1-blending;
  532.             break;
  533.               case XK_G:
  534.               case XK_g:
  535.             if (dzrot != 0.0) {
  536.                 dzrot = 0.0;
  537.             } else {
  538.                 dzrot = 0.2;
  539.             }
  540.             break;
  541.               case XK_q:
  542.               case XK_Q:
  543.             mode1 = 1;
  544.             break;
  545.               case XK_w:
  546.               case XK_W:
  547.             mode1 = 0;
  548.             break;
  549.               case XK_e:
  550.               case XK_E:
  551.             mode2 = 2;
  552.             ci = COLOR_OFFSET;
  553.             break;
  554.               case XK_r:
  555.               case XK_R:
  556.             mode2 = 1;
  557.             ci = COLOR_OFFSET;
  558.             break;
  559.               case XK_t:
  560.               case XK_T:
  561.             mode2 = 0;
  562.             ci = YELLOW;
  563.             break;
  564.               case XK_a:
  565.               case XK_A:
  566.             if (mode2) {
  567.                 size += 0.25;
  568.             } else {
  569.                 size ++;
  570.             }
  571.             break;
  572.               case XK_z:
  573.               case XK_Z:
  574.             if (mode2) {
  575.                 size -= 0.25;
  576.             } else {
  577.                 size --;
  578.             }
  579.             if (size < 1) {
  580.                 size = 1;
  581.             }
  582.             break;
  583.               case XK_D:
  584.               case XK_d:
  585.             dither = !dither;
  586.             if (dither) {
  587.                 glEnable(GL_DITHER);
  588.                 printf("Dithering on\n");
  589.             } else {
  590.                 glDisable(GL_DITHER);
  591.                 printf("Dithering off\n");
  592.             }
  593.             break;
  594.               case XK_F:
  595.               case XK_f:
  596.             fragment = !fragment;
  597.             if (fragment) {
  598.                 printf("Fragmenting\n");
  599.             } else {
  600.                 printf("No fragmenting\n");
  601.             }
  602.             break;
  603.               case XK_S:
  604.               case XK_s:
  605.             smoothModel = !smoothModel;
  606.             if (smoothModel) {
  607.                 printf("Smooth shading\n");
  608.                 glShadeModel(GL_SMOOTH);
  609.             } else {
  610.                 printf("Flat shading\n");
  611.                 glShadeModel(GL_FLAT);
  612.             }
  613.             break;
  614.               case XK_X:
  615.               case XK_x:
  616.             stenciling = !stenciling;
  617.             if (stenciling) {
  618.                 printf("Stenciling\n");
  619.             } else {
  620.                 printf("Not stenciling\n");
  621.             }
  622.             break;
  623.               case XK_C:
  624.               case XK_c:
  625.             depthtest = !depthtest;
  626.             if (depthtest) {
  627.                 printf("Depth testing\n");
  628.             } else {
  629.                 printf("No depth testing\n");
  630.             }
  631.             break;
  632.               case XK_V:
  633.               case XK_v:
  634.             alwayspass = !alwayspass;
  635.             if (alwayspass) {
  636.                 printf("Always pass\n");
  637.             } else {
  638.                 printf("Not always pass\n");
  639.             }
  640.             break;
  641.               case XK_B:
  642.               case XK_b:
  643.             depthMask = !depthMask;
  644.             if (depthMask) {
  645.                 printf("Depth writes masked for horizontal lines\n");
  646.             } else {
  647.                 printf("Depth writes not masked\n");
  648.             }
  649.             break;
  650.               default:
  651.             setNeed = GL_FALSE;
  652.             break;
  653.             }
  654.             if (setNeed) needDisplay = GL_TRUE;
  655.         }
  656.         break;
  657.         }
  658.     } while (XPending(dpy) != 0);
  659.  
  660.     if (dzrot != 0.0 || needDisplay) {
  661.         needDisplay = GL_FALSE;
  662.         Redraw();
  663.     }
  664.     }
  665. }
  666.